const { Payment, Order, User, SystemLog } = require('../models');
const { AppError } = require('../middlewares/errorHandler');
const { logger } = require('../utils/logger');
const { v4: uuidv4 } = require('uuid');
const config = require('../config');
const crypto = require('crypto');

class PaymentController {
  /**
   * 创建支付
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async createPayment(ctx) {
    const { orderId, amount, method } = ctx.request.body;
    const userId = ctx.state.user.id;

    // Find order
    const order = await Order.findOne({
      where: { id: orderId, userId }
    });

    if (!order) {
      throw new AppError(404, 'Order not found');
    }

    if (order.status !== 'pending') {
      throw new AppError(400, 'Order is not in pending status');
    }

    // Create payment
    const payment = await Payment.create({
      orderId,
      amount,
      method,
      transactionId: uuidv4(),
      status: 'pending'
    });

    // Update order status
    await order.update({ status: 'processing' });

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'create_payment',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Payment created for order: ${order.orderNumber}`
    });

    ctx.status = 201;
    ctx.body = {
      status: 'success',
      data: { payment }
    };
  }

  /**
   * 处理支付
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async processPayment(ctx) {
    const { id } = ctx.params;
    const { status } = ctx.request.body;
    const userId = ctx.state.user.id;

    const payment = await Payment.findOne({
      where: { id },
      include: [{ model: Order }]
    });

    if (!payment) {
      throw new AppError(404, 'Payment not found');
    }

    if (payment.Order.userId !== userId) {
      throw new AppError(403, 'Not authorized');
    }

    // Update payment status
    await payment.update({
      status,
      paymentTime: status === 'success' ? new Date() : null
    });

    // Update order status
    if (status === 'success') {
      await payment.Order.update({ 
        status: 'paid',
        completedAt: new Date()
      });

      // Update user points if applicable
      if (payment.Order.type === 'recharge') {
        const user = await User.findByPk(userId);
        await user.update({
          points: user.points + payment.Order.points
        });
      }
    } else if (status === 'failed') {
      await payment.Order.update({ status: 'pending' });
    }

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'process_payment',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Payment ${payment.transactionId} processed with status: ${status}`
    });

    ctx.body = {
      status: 'success',
      data: { payment }
    };
  }

  /**
   * 退款支付
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async refundPayment(ctx) {
    const { id } = ctx.params;
    const { reason } = ctx.request.body;
    const userId = ctx.state.user.id;

    const payment = await Payment.findOne({
      where: { id },
      include: [{ model: Order }]
    });

    if (!payment) {
      throw new AppError(404, 'Payment not found');
    }

    if (payment.Order.userId !== userId) {
      throw new AppError(403, 'Not authorized');
    }

    if (payment.status !== 'success') {
      throw new AppError(400, 'Payment cannot be refunded');
    }

    // Update payment status
    await payment.update({
      status: 'refunded',
      refundTime: new Date()
    });

    // Update order status
    await payment.Order.update({
      status: 'refunded',
      refundedAt: new Date()
    });

    // Revert user points if applicable
    if (payment.Order.type === 'recharge') {
      const user = await User.findByPk(userId);
      await user.update({
        points: user.points - payment.Order.points
      });
    }

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'refund_payment',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Payment ${payment.transactionId} refunded. Reason: ${reason}`
    });

    ctx.body = {
      status: 'success',
      message: 'Payment refunded successfully'
    };
  }

  /**
   * 获取支付列表
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getPayments(ctx) {
    const userId = ctx.state.user.id;

    const payments = await Payment.findAll({
      include: [{
        model: Order,
        where: { userId },
        attributes: ['orderNumber', 'type', 'status']
      }]
    });

    ctx.body = {
      status: 'success',
      data: { payments }
    };
  }

  /**
   * 获取单个支付
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getPayment(ctx) {
    const { id } = ctx.params;
    const userId = ctx.state.user.id;

    const payment = await Payment.findOne({
      where: { id },
      include: [{
        model: Order,
        where: { userId }
      }]
    });

    if (!payment) {
      throw new AppError(404, 'Payment not found');
    }

    ctx.body = {
      status: 'success',
      data: { payment }
    };
  }

  /**
   * 处理微信支付回调
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async handleWechatNotify(ctx) {
    const { appId } = ctx.params;
    const rawBody = ctx.request.rawBody;
    const signature = ctx.get('Wechatpay-Signature');
    const timestamp = ctx.get('Wechatpay-Timestamp');
    const nonce = ctx.get('Wechatpay-Nonce');
    const serial = ctx.get('Wechatpay-Serial');

    // 验证签名
    const wechatConfig = config.wechat.apps.find(app => app.appId === appId);
    if (!wechatConfig) {
      throw new AppError(404, '未找到对应的微信应用配置');
    }

    const message = `${timestamp}\n${nonce}\n${rawBody}\n`;
    const verify = crypto.createVerify('RSA-SHA256');
    verify.update(message);
    const isSignatureValid = verify.verify(wechatConfig.platformCertificate, signature, 'base64');

    if (!isSignatureValid) {
      throw new AppError(400, '回调签名验证失败');
    }

    // 解析回调数据
    const data = JSON.parse(rawBody.toString());
    
    // 处理支付结果
    const payment = await Payment.findOne({
      where: { 
        transactionId: data.transaction_id,
        method: 'wechat'
      }
    });

    if (!payment) {
      throw new AppError(404, '未找到对应的支付记录');
    }

    // 更新支付状态
    if (data.trade_state === 'SUCCESS') {
      await payment.update({
        status: 'completed',
        paidAt: new Date(),
        response: data
      });

      // 更新订单状态
      const order = await Order.findByPk(payment.orderId);
      if (order) {
        await order.update({ status: 'paid' });
      }

      // 记录操作日志
      await SystemLog.create({
        action: 'payment_completed',
        target_type: 'payment',
        target_id: payment.id,
        details: { payment, notifyData: data }
      });
    } else if (['CLOSED', 'REVOKED', 'PAYERROR'].includes(data.trade_state)) {
      await payment.update({
        status: 'failed',
        response: data
      });

      // 记录操作日志
      await SystemLog.create({
        action: 'payment_failed',
        target_type: 'payment',
        target_id: payment.id,
        details: { payment, notifyData: data }
      });
    }

    // 返回成功响应
    ctx.body = {
      code: 'SUCCESS',
      message: '成功'
    };
  }

  /**
   * 处理支付宝回调
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async handleAlipayNotify(ctx) {
    const notifyData = ctx.request.body;

    // 验证签名
    const signType = notifyData.sign_type.toUpperCase();
    const sign = notifyData.sign;
    
    // 移除签名字段
    delete notifyData.sign;
    delete notifyData.sign_type;

    // 按字母顺序排序所有字段
    const sortedParams = Object.keys(notifyData).sort().map(key => 
      `${key}=${notifyData[key]}`
    ).join('&');

    const verify = crypto.createVerify(signType === 'RSA2' ? 'RSA-SHA256' : 'RSA-SHA1');
    verify.update(sortedParams, 'utf8');
    const isSignatureValid = verify.verify(
      config.alipay.publicKey,
      sign,
      'base64'
    );

    if (!isSignatureValid) {
      throw new AppError(400, '回调签名验证失败');
    }

    // 处理支付结果
    const payment = await Payment.findOne({
      where: {
        transactionId: notifyData.trade_no,
        method: 'alipay'
      }
    });

    if (!payment) {
      throw new AppError(404, '未找到对应的支付记录');
    }

    // 更新支付状态
    if (notifyData.trade_status === 'TRADE_SUCCESS') {
      await payment.update({
        status: 'completed',
        paidAt: new Date(),
        response: notifyData
      });

      // 更新订单状态
      const order = await Order.findByPk(payment.orderId);
      if (order) {
        await order.update({ status: 'paid' });
      }

      // 记录操作日志
      await SystemLog.create({
        action: 'payment_completed',
        target_type: 'payment',
        target_id: payment.id,
        details: { payment, notifyData }
      });
    } else if (['TRADE_CLOSED', 'TRADE_FINISHED'].includes(notifyData.trade_status)) {
      await payment.update({
        status: 'failed',
        response: notifyData
      });

      // 记录操作日志
      await SystemLog.create({
        action: 'payment_failed',
        target_type: 'payment',
        target_id: payment.id,
        details: { payment, notifyData }
      });
    }

    // 返回成功响应
    ctx.body = 'success';
  }
}

module.exports = new PaymentController(); 